package cn.open.feishu.alert.log;

import cn.open.feishu.alert.support.FeishuAlertService;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.event.Level;
import java.lang.reflect.Method;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @Description 日志处理器(错误日志告警处理)
 * @Author fandy.lin
 * @Date 2021/11/17 1:53 下午
 **/
@Slf4j
@Getter
@AllArgsConstructor
public class LoggerHandler {
    FeishuAlertService feishuAlertService;
    private static final Pattern compile = Pattern.compile("\\{\\}");

    public void handleLog(Method method, Object[] args) {
        //1、告警发送过滤
        if (!isSendAlert(method, args)) {
            return;
        }
        //2、构建消息体
        String pattern = (String) args[0];
        String text = formatText(pattern, args);
        //3、发送告警
        feishuAlertService.sendAwait(null, pattern, text);
    }

    public String formatText(String pattern, Object[] args) {
        args = parseArgs(args);
        Matcher matcher = compile.matcher(pattern);
        StringBuffer text = new StringBuffer();
        int i = 1;
        while (matcher.find()) {
            if (i < args.length) {
                matcher.appendReplacement(text, parseString(args[i]));
                i++;
            }
        }
        matcher.appendTail(text);
        while (i < args.length) {
            text.append(">>").append(parseString(args[i]));
            i++;
        }
        return text.toString();
    }

    private Object[] parseArgs(Object[] args) {
        final int lenSize = 2;
        if (args.length == lenSize && args[1].getClass().isArray()) {
            Object[] params = (Object[]) args[1];
            args = new Object[params.length + 1];
            for (int i = 0; i < params.length; i++) {
                args[i + 1] = params[i];
            }
        }
        return args;
    }

    private String parseString(Object o) {
        if (String.class.isAssignableFrom(o.getClass())) {
            return (String) o;
        } else {
            return o.toString();
        }
    }

    private boolean isSendAlert(Method method, Object[] args) {
        //筛选错误日志
        if (!Level.ERROR.toString().toLowerCase().equals(method.getName())) {
            return false;
        }
        //空参过滤
        if (args == null) {
            return false;
        }
        //非格式化日志类型过滤
        if (!(args[0] instanceof String)) {
            return false;
        }
        return true;
    }
}